package zserver

import (
	"fmt"
	"net"

	"gitee.com/colin0724/zserver/utils"
	"gitee.com/colin0724/zserver/ziface"
	"gitee.com/colin0724/zserver/znet"
)

type Server struct {
	Name string
	//tcp4 or other
	IPVersion   string
	IP          string
	Port        int
	PackParser  ziface.IPack
	msgHandler  ziface.IMsgHandle
	ConnMgr     ziface.IConnManager
	OnConnStart func(conn ziface.IConnection)
	OnConnStop  func(conn ziface.IConnection)
}

func NewServer() ziface.IServer {
	return &Server{
		PackParser: &znet.BasePack{},
		Name:       utils.GlobalObject.Name,
		IPVersion:  "tcp4",
		IP:         utils.GlobalObject.Host,
		Port:       utils.GlobalObject.Port,
		msgHandler: znet.NewMsgHandle(),
		ConnMgr:    znet.NewConnManager(),
	}
}

func (s *Server) RegisterPackParser(parser ziface.IPack) {
	s.PackParser = parser
}

func (s *Server) Start() {
	fmt.Printf("[START] Server name: %s,listenner at IP: %s, Port %d is starting\n", s.Name, s.IP, s.Port)

	go func() {
		s.msgHandler.StartWorkerPool()

		addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
		if err != nil {
			fmt.Println("resolve tcp addr err: ", err)
			return
		}

		listener, err := net.ListenTCP(s.IPVersion, addr)
		if err != nil {
			fmt.Println("listen", s.IPVersion, "err", err)
			return
		}

		fmt.Println("start ", s.Name, " server succ, now listenning...")

		var cid uint32
		cid = 0

		for {
			conn, err := listener.AcceptTCP()
			if err != nil {
				fmt.Println("Accept err ", err)
				continue
			}

			// fmt.Println("Get conn remote addr = ", conn.RemoteAddr().String())

			if s.ConnMgr.Len() >= utils.GlobalObject.MaxConn {
				conn.Close()
				continue
			}

			dealConn := znet.NewConntion(s, conn, cid, s.msgHandler)
			cid++

			go dealConn.Start()
		}
	}()
}

//停止服务
func (s *Server) Stop() {
	fmt.Println("[STOP] Server, name ", s.Name)
	s.ConnMgr.ClearConn()
}

//运行服务
func (s *Server) Serve() {
	s.Start()

	select {}
}

//路由功能：给当前服务注册一个路由业务方法，供客户端链接处理使用
func (s *Server) AddRouter(msgId uint16, router ziface.IRouter) {
	s.msgHandler.AddRouter(msgId, router)
}

func (s *Server) GetConnMgr() ziface.IConnManager {
	return s.ConnMgr
}

func (s *Server) SetOnConnStart(hookFunc func(ziface.IConnection)) {
	s.OnConnStart = hookFunc
}

func (s *Server) SetOnConnStop(hookFunc func(ziface.IConnection)) {
	s.OnConnStop = hookFunc
}

func (s *Server) CallOnConnStart(conn ziface.IConnection) {
	if s.OnConnStart != nil {
		// fmt.Println("---> CallOnConnStart....")
		s.OnConnStart(conn)
	}
}

func (s *Server) CallOnConnStop(conn ziface.IConnection) {
	if s.OnConnStop != nil {
		// fmt.Println("---> CallOnConnStop....")
		s.OnConnStop(conn)
	}
}
